#pragma once

namespace snow
{
    template<class T, class Container = deque<T>>
    class stack
    {
    public:
        //stack();

        void push(const T& x)
        {
            _c.push_back(x);
        }

        void pop()
        {
            assert(!_c.empty());
            _c.pop_back();
        }

        T& top()
        {
            assert(!_c.empty());
            return _c.back();
        }

        const T& top()const
        {
            assert(!_c.empty());
            return _c.back();
        }

        size_t size()const
        {
            return _c.size();
        }

        bool empty()const
        {
            return _c.empty();
        }
        
    private:
        Container _c;
    };



    template<class T, class Container = deque<T>>
    class queue
    {
    public:
        //queue();

        void push(const T& x)
        {
            _c.push_back(x);
        }

        void pop()
        {
            assert(!_c.empty());
            _c.pop_front();
        }

        T& back()
        {
            assert(!_c.empty());
            return _c.back();
        }

        const T& back()const
        {
            assert(!_c.empty());
            return _c.back();
        }

        T& front()
        {
            assert(!_c.empty());
            return _c.front();
        }

        const T& front()const
        {
            assert(!_c.empty());
            return _c.frnot();
        }

        size_t size()const
        {
            return _c.size();
        }

        bool empty()const
        {
            return _c.empty();
        }

    private:
        Container _c;
    };


    void test_stack()
    {
        stack<int> st;
        cout << st.empty() << endl;
        st.push(1);
        st.push(2);
        cout << st.size() << endl;
        st.push(3);
        st.push(4);
        st.push(5);
        cout << st.top() << endl;
        cout << st.size() << endl;
        st.pop();
        cout << st.top() << endl;
        cout << st.empty() << endl;
        cout << st.size() << endl;
    }

    void test_queue()
    {
        queue<int> q;
        cout << q.empty() << endl;
        q.push(1);
        q.push(2);
        cout << q.size() << endl;
        q.push(3);
        q.push(4);
        q.push(5);
        cout << q.front() << endl;
        cout << q.back() << endl;
        cout << q.size() << endl;
        q.pop();
        cout << q.front() << endl;
        cout << q.back() << endl;
        cout << q.empty() << endl;
        cout << q.size() << endl;
    }
};